#include "face.h"
#include "face_common.h"
#include "sensetime_protocol.h"
#include "face_encrypt.h"

/* debug print interface */
#if defined(FACE_DEBUG)
#define FACE_TASK_DEBUG_LOG(format, ...) OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#define __FACE_TASK_DEBUG_LOG(format, ...) __OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#else
#define FACE_TASK_DEBUG_LOG(format, ...)
#define __FACE_TASK_DEBUG_LOG(format, ...) //__OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#endif
#define FACE_TASK_LOG(format, ...) OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#define __FACE_TASK_LOG(format, ...) __OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)

/* virtual hardware interface */
#define VHW_PIN_5V_POWER vPIN_C32		//人脸和掌静脉5V控制
#define VHW_PIN_FACE_POWER vPIN_C7
#define VHW_UART_FACE vUART_3

/* face power control */
#define FACE_MODULE_POWER_ON Device_Write(VHW_PIN_FACE_POWER, NULL, 0, 1)
#define FACE_MODULE_POWER_OFF Device_Write(VHW_PIN_FACE_POWER, NULL, 0, 0)
#define FP5V_POWER_ON Device_Write(VHW_PIN_5V_POWER, NULL, 0, 1)		//人脸和掌静脉5V控制
#define FP5V_POWER_OFF Device_Write(VHW_PIN_5V_POWER, NULL, 0, 0)

#define FACE_NV_SIZE sizeof(NvFace_stu_t)

#define MASTER_TO_FACE_MSG_NUM 10						  //主控给人脸的循环消息队列深度
#define FACE_POWER_ON_TIMEOUT	1500						//开机超时时间

static RingBufferHandle_t uartFace_rbHandle = NULL;		//人脸串口接收数据的队列句柄	
static RingBufferHandle_t MasterOperate_rbHandle = NULL; /* 应用层操作循环队列句柄 */

/*OTA升级子状态处理和切换*/
static FaceOtaStatus_enum_t FaceOtaStatus = OTA_IDLE_STATUS;

static uint16_t id_to_delete = 0;		//被删除的人脸id

#pragma pack(1)
typedef struct
{
	uint8_t faceReleaseFlag;			  //人脸经过产测，出厂状态标志 0:未产测    1：产测(已量产)
	uint8_t faceSn[FACE_SN_LEN];		  //人脸模组sn
	uint8_t faceModel[FACE_MODEL_LEN];    //人脸型号
	uint8_t faceVesion[FACE_VERSION_LEN]; //人脸软件版本
	uint16_t face_user_id[MAX_FACE_NUM];
} NvFace_stu_t;

typedef struct
{
	Face_status_enum_t curStatus; //人脸模组当前状态
	Face_mode_enum_t curMode;	  //人脸模组当前的工作模式
	Face_operate_id_enum_t operateId;		//人脸当前操作id
	AllowStatus allowBreakIn;	  //当前人脸执行流程    ALLOW:允许打断；    DISALLOW:不允许打断
	uint32_t start_time;		  //起始时间
	uint32_t timeout;			  //超时时间
	FlagStatus busy;			  //当前是否忙状态， SET：忙（只能被终止指令打断，其它事件无法打断）    RESET：可接受外部指令
								  
} Face_Status_stu_t;

#pragma pack()

/*删除的人脸编号*/
static struct
{
	uint16_t userId; //需要删除的人脸ID（存储于人脸模组）
	uint8_t userNum; //人脸用户编号（存储于锁）
} faceDeleteUser;


static Face_Status_stu_t faceModuleStatus //人脸模组状态
	= {
		.curStatus = FACE_STATUS_POWER_DOWN,	 //人脸模组当前状态
		.curMode = FACE_MODULE_SLEEPED_MODE, //人脸模组当前的工作模式
		.allowBreakIn = ALLOW,
		.timeout = FOREVER_TIME_OUT,
		//.LowPower = UNKNOW,
};

Face_Param_stu_t faceMsgParam;

/*****************************************************************************************************************************/

static FlagStatus faceTaskNoFaceFlag = RESET; //未检测到人脸标志  SET：未检测到人脸   RESET：检测到人脸

/* 回调函数 */
static FaceMessageCallback_fun_t pCmdCallback = NULL;



static void Face_Mode_SeletDeal(Face_DealParam_stu_t *param);
static void Face_Event_Update(void);


/**
  * @brief  故障处理
  * @note
  * @param  err：是否故障
  * @return void
  */
static void err_process(uint8_t err)
{
	static uint8_t err_flag = 0xff;
    if (err != err_flag)
    {
        err_flag = err;
        OSAL_MessagePublishErrorCode(ERRCODE_TYPE_FACE, err_flag);
    }
}

/**
  * @brief  读取量产标志位
  */
static uint8_t Face_ReadFaceReleaseFlag(void)
{
	uint8_t faceReleaseFlag;
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceReleaseFlag), &faceReleaseFlag, 1);
	return faceReleaseFlag;
}

/**
  * @brief  写量产标志位
  * @note	This flag will be reset every time the program is re-burned 
  *
  * @param  0:not set    1:set
  */
static ErrorStatus Face_SetFaceReleaseFlag(uint8_t flag)
{
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceReleaseFlag), &flag, 1);
}


/**
  * @brief  人脸检测标志设置初始值
  *
  * @note  每次启动验证时置位标志为已经检测到人脸
  */
static void Face_CheckFlag_Init(void)
{
	faceTaskNoFaceFlag = RESET;
}

/**
  * @brief  未检测到人脸标志置位
  *
  * @note
  */
static void Face_Check(void *pdata)
{
	Face_NoteFaceStatus_stu_t *pdatabuf = (Face_NoteFaceStatus_stu_t *)pdata;
	/*未检测到人脸标志  SET：未检测到人脸   RESET：检测到人脸*/
	faceTaskNoFaceFlag = (pdatabuf->status == FACE_STATE_NOFACE) ? SET : RESET;
}

/**
  * @brief  判断是否检测到人脸
  *
  * @return SET：未检测到人脸   
  * 		RESET：检测到人脸
  */
static FlagStatus Face_Check_Result(void)
{
	/*未检测到人脸标志  SET：未检测到人脸   RESET：检测到人脸*/
	FlagStatus ret = (faceTaskNoFaceFlag == SET) ? SET : RESET;
	return ret;
}

/**
  * @brief  写入人脸内部id
  */
ErrorStatus Face_WriteUserId(uint8_t num, uint8_t *userId)
{
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, userId, 2);
}

/**
  * @brief  读取人脸内部id
  */
ErrorStatus Face_ReadUserId(uint8_t num, uint8_t *userId)
{
	return OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, userId, 2);
}

/**
  * @brief  删除单个人脸索引
  * @param  num : 索引号
  */
ErrorStatus Face_DeleteIndex(uint8_t num)
{
	uint16_t userId = 0xffff;
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, (void *)&userId, 2);
}

/**
  * @brief  删除所有人脸索引数据
  */
ErrorStatus Face_DeleteAllIndex(void)
{
	uint16_t userId[MAX_FACE_NUM];
	memset(userId, 0xff, sizeof(userId));
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, face_user_id), (void *)&userId, sizeof(userId));
}

/**
  * @brief  根据人脸id搜索索引号
  * @param  userId : 人脸ID
  */
int32_t Face_Search_Index(uint8_t *userId)
{
	uint8_t read[2];
	int num = 0;
	for(num = 0; num < MAX_FACE_NUM; num++)
	{
		OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, &read, sizeof(read));
		printf("%d : 0x%04x\r\n", num, *(uint16_t *)read);
		if(*(uint16_t *)read == *(uint16_t *)userId)
		{
			return num;
		}
	}
	return -1;
}

uint8_t read_buff[MAX_FACE_NUM*2];

/**
  * @brief  读取所有人脸id
  * 
  */
void Face_Read_All_UserId(void)
{
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, face_user_id), &read_buff, sizeof(read_buff));
}


/**
  * @brief  人脸查询比较
  * @param  module_userId : 人脸ID
  */
int32_t Face_Search_Compare(uint8_t *module_userId)
{
	uint8_t read[2];
	int num = 0;

	for(num = 0; num < MAX_FACE_NUM; num++)
	{
		//每次读取一个id进行比较
		memcpy(read,read_buff+num*2,2);
		//OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, face_user_id) + num * 2, &read, sizeof(read));
		//FACE_TASK_LOG("%d : %x", num, *(uint16_t *)read);
		if(*(uint16_t *)read == *(uint16_t *)module_userId)
		{
			printf("[%02d]    : 0x%04x \r\n",num,*(uint16_t *)module_userId);
			return 1;
		}
	}
	return 0;
}

/**
  * @brief  返回锁当前的时间戳
  *
  * @return 返回UTC时间（以 1970.1.1 00:00:00 为起始时间的秒计数）
  */
static uint32_t Face_GetUtcTimestamp(void)
{
	uint32_t timestamp;
	OSAL_TimeGet(&timestamp, T_UTC);
	return timestamp;
}

/**
  * @brief  写人脸模块版本号
  */
ErrorStatus Face_WriteFaceVersion(uint8_t *pData, uint8_t len)
{
	ErrorStatus status = SUCCESS;
	uint8_t temp[FACE_VERSION_LEN] = {0};
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceVesion), temp, FACE_VERSION_LEN);
	if (strcmp((char *)pData, (char *)&temp) != 0)
	{
		FACE_TASK_LOG("update face version: %s\r\n", pData);
		status = OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceVesion), pData, FACE_VERSION_LEN);
	}

	return status;
}

/**
  * @brief  读人脸版本号
  */
static ErrorStatus Face_Read_Version(uint8_t *pData, uint8_t *pLen)
{
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceVesion), pData, FACE_VERSION_LEN);
	uint8_t version_len = strlen(pData);
	for (int i = 1; i < version_len; i++)
	{
		if (!((pData[i] >= '0' && pData[i] <= '9') || pData[i] == '.'))
		{
			return ERROR;
		}
	}
	*pLen = version_len;
	FACE_TASK_LOG("read face version: %s\r\n", pData);
	return SUCCESS;
}

/**
  * @brief  read face model读人脸型号
  */
static ErrorStatus Face_Read_Model(uint8_t *pData)
{
	ErrorStatus ret = OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceModel), pData, FACE_MODEL_LEN);
	FACE_TASK_LOG("read face model: %s\r\n", pData);
	return ret;
}

/**
  * @brief  write face model
  */
ErrorStatus Face_Write_Model(uint8_t *pData)
{
	ErrorStatus status = SUCCESS;
	uint8_t temp[FACE_MODEL_LEN] = {0};
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceModel), temp, FACE_MODEL_LEN);
	if (strcmp((char *)pData, (char *)&temp) != 0)
	{
		FACE_TASK_LOG("update face model: %s\r\n", pData);
		status = OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceModel), pData, FACE_MODEL_LEN);
	}
	return status;
}

/**
  * @brief 读人脸SN
  */
static ErrorStatus Face_ReadFaceSN(uint8_t *pSN)
{
	int i = 0;
	ErrorStatus ret = ERROR;
	OSAL_NvRead(OSAL_OFFSET(NvFace_stu_t, faceSn), pSN, FACE_SN_LEN);
	for (i = 0; i < FACE_SN_LEN; i++)
	{
		if (!((pSN[i] >= '0' && pSN[i] <= '9') || (pSN[i] >= 'a' && pSN[i] <= 'z') || (pSN[i] >= 'A' && pSN[i] <= 'Z') || (pSN[i] == '-')))
		{
			break;
		}
	}
	if (i >= FACE_SN_LEN - 5) //支持15~20的变长  人脸模组技术支持答复人脸sn长度为17~20个字节
	{
		ret = SUCCESS;
	}
	return ret;
}

/**
  * @brief  写人脸SN
  */
static ErrorStatus Face_WriteFaceSN(uint8_t *pSN, uint8_t len)
{
	return OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceSn), pSN, FACE_SN_LEN);
}

/**
  * @brief  人脸模组初始化加密密钥处理函数
  *
  * @note
  */
static void Face_InitEncryption_Process(void)
{
	uint8_t seeddata[4] = {0};
	uint32_t timedata = 0;
	FaceEncrypt_GenerateRandomNumber(seeddata); //获取随机数
	timedata = Face_GetUtcTimestamp();			//获取时间
	Sensetime_Send_InitEncryption_CMD(seeddata, 4, (uint8_t *)&timedata, 4);
	FaceEncrypt_GenencKey(seeddata); //生成aes密钥
}

/************************************************************************************************/
/*****************************  人脸推送消息选择函数    STATR   ***********************************/
/************************************************************************************************/

/**
  * @brief  推送人脸消息
  * @note   人脸模块产生的动作，通知主任务
  *         
  * @param  FaceActionType_enum_t:事件类型
  * @param  id:用户ID
  */
static void Face_PublishMsg(FaceActionType_enum_t action, uint8_t id)
{
	FaceMsg_t faceMsg;
	faceMsg.action = action;
	faceMsg.id = id;
	OSAL_MessagePublish(&faceMsg, sizeof(faceMsg));
}


/**
  * @brief  人脸录入结果推送
  *
  * @note
  */
static void Face_Enroll_SendActionMsg(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;

	switch (result)
	{
		case RESULT_SUCCESS_REPORT:
			action = FACE_ACTION_ADD_OK;
			break;
		case RESULT_FAIL_REPORT:
			action = FACE_ACTION_ADD_ERR;
			break;
		case RESULT_FACE_ENROLLED:
			action = FACE_ACTION_ADD_REPEAT;
			break; //人脸已存在
		default:
			break;
	}

	if (FACE_ACTION_MAX != action)
	{
		Face_PublishMsg(action, numbuf);
	}
}

/**
  * @brief  人脸验证结果推送
  *
  * @note
  */
static void Face_Verify_SendActionMsg(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;

	switch (result)
	{
		case RESULT_SUCCESS_REPORT:
			action = FACE_ACTION_VERIFY_OK;
			break;
		case RESULT_FAIL_REPORT:
			action = FACE_ACTION_VERIFY_ERR;
			break;

		case RESULT_END:
			action = FACE_ACTION_VERIFY_END;
			break;

		case RESULT_NO_FACE:			   //未检测到人脸
			action = FACE_ACTION_TIME_OUT; //无人脸，以超时结果上报
			break;

		case RUSULT_MODULE_BREAKDOWN:
			action = FACE_ACTION_MODULE_BREAKDOWN;
		default:
			break;
	}

	if (FACE_ACTION_MAX != action)
	{
		Face_PublishMsg(action, numbuf);
	}
}

/**
  * @brief  人脸删除结果发送给主任务
  *
  * @note
  */
static void Face_Delete_SendActionMsg(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;
	FACE_TASK_LOG("delete send msg ,result:%d",result);

	switch (result)
	{
		case RESULT_SUCCESS_REPORT:
			action = FACE_ACTION_DEL_OK;
			break;

		case RESULT_FAIL_REPORT:
			action = FACE_ACTION_DEL_FAIL;
			break; //人脸已存在

		case RESULT_NO_FACE:
			action = FACE_ACTION_TIME_OUT;
			break; //无人脸，以超时结果上报
		default:

			break;
	}

	if (FACE_ACTION_MAX != action)
	{
		Face_PublishMsg(action, numbuf);
	}
}

/**
  * @brief  人脸升级结果发送给主任务
  *
  * @note
  */
static void Face_Ota_SendActionMsg(Face_Result_enum_t result, uint8_t num)
{
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	uint8_t numbuf = num;
	switch (result)
	{
		case RESULT_SUCCESS_REPORT:
			action = FACE_ACTION_OTA_OK;
			break;
		case RESULT_FAIL_REPORT:
			action = FACE_ACTION_OTA_ERR;
			break; //OTA失败
		default:
			break;
	}
	if (FACE_ACTION_MAX != action)
	{
		Face_PublishMsg(action, numbuf);
	}
}

/**
  * @brief  根据人脸模组返回“人脸方向错误”判断人脸偏转方向
  *
  * @note
  */
static FaceActionType_enum_t Face_Single_Enroll_ERR_Dir_Reminder(int16_t yaw, int16_t pitch, int16_t roll)
{
	FaceActionType_enum_t ret = FACE_ACTION_MAX;
	FACE_TASK_LOG("siggle enroll yaw=%#2x,pitch=%#2x, roll=%#2x", yaw, pitch, roll);
	if (yaw > FACE_MIDDLE_MAX)
	{
		ret = FACE_ACTION_LEFT_REMINDER;
	}
	else if (yaw < FACE_MIDDLE_MIN)
	{
		ret = FACE_ACTION_RIGHT_REMINDER;
	}

	else if (pitch > FACE_MIDDLE_MAX)
	{
		ret = FACE_ACTION_UP_REMINDER;
	}
	else if (pitch < FACE_MIDDLE_MIN)
	{
		ret = FACE_ACTION_DOWN_REMINDER;
	}

	else if (roll > FACE_ROLL_MAX //歪头
			 || roll < FACE_ROLL_MIN)
	{
		ret = FACE_ACTION_MIDDLE_REMINDER;
	}
	return ret;
}

/**
  * @brief  录入和验证过程人脸状态提醒
  *
  * @note
  */
static void Face_FaceStatus_Reminder(void *pdata)
{
	uint8_t num = INVALID_NUM;
	FaceActionType_enum_t action = FACE_ACTION_MAX;
	s_note_data_face *pdatabuf = (s_note_data_face *)pdata;
	//FACE_TASK_DEBUG_LOG("FaceStatus:state:%#4x,left:%#4x,  top:%#4x,	right:%#4x, bottom:%#4x, yaw:%#4x, pitch:%#4x, roll:%#4x,",\
									pdata->state,pdata->left,pdata->top,	pdata->right,pdata->bottom,pdata->yaw,pdata->pitch,pdata->roll);
	FACE_TASK_LOG("FaceStatus:state:%d", pdatabuf->status);

	switch (pdatabuf->status)
	{
		case FACE_STATE_TOOUP: //人脸太靠近图片上边沿
			action = FACE_ACTION_TOOUP;
			break;
		case FACE_STATE_TOODOWN: //人脸太靠近图片下边沿
			action = FACE_ACTION_TOODOWN;
			break;
		case FACE_STATE_TOOLEFT: //人脸太靠近图片左边沿 (模组回复的方向左右是反的)
			action = FACE_ACTION_TOOLRIGHT;
			break;
		case FACE_STATE_TOOLRIGHT: //人脸太考经图片右边沿(模组回复的方向左右是反的)
			action = FACE_ACTION_TOOLEFT;
			break;
		case FACE_STATE_FAR: //人脸距离太远
			action = FACE_ACTION_FAR;
			break;
		case FACE_STATE_CLOSE: //人脸距离太近
			action = FACE_ACTION_CLOSE;
			break;
		case FACE_STATE_EYEBROW_OCCLUSION: //眉毛遮挡
			action = FACE_ACTION_EYEBROW_OCCLUSION;
			break;
		case FACE_STATE_EYE_OCCLUSION: //眼睛遮挡
			action = FACE_ACTION_EYE_OCCLUSION;
			break;
		case FACE_STATE_FACE_OCCLUSION: //脸部遮挡
			action = FACE_ACTION_FACE_OCCLUSION;
			break;
		case FACE_STATE_NOFACE:
			action = FACE_ACTION_NOFACE;
			break;
		case FACE_STATE_DIRECTION_ERROR: //录入人脸方向错误
			action = Face_Single_Enroll_ERR_Dir_Reminder(pdatabuf->yaw, pdatabuf->pitch, pdatabuf->roll);
			action = (action == FACE_ACTION_MAX) ? FACE_ACTION_DIRECTION_ERROR : action;

			break;

		default:
			break;
	}

	if (FACE_ACTION_MAX != action)
	{
		Face_PublishMsg(action, num);
	}

}


/**
  * @brief  人脸事件更新处理
  *
  * @note
  */
static void Face_Event_Update(void)
{
	Face_DealParam_stu_t parambuf;
	parambuf.data = NULL;
	FACE_TASK_LOG("cur operateId:%d\r\n",faceModuleStatus.operateId);

	switch (faceModuleStatus.operateId)
	{
			//录入人脸
		case OPERATE_ID_ENROLL:
			parambuf.event = FACE_EVENT_START_ENROLL;
			break;

			//验证人脸
		case OPERATE_ID_VERIFY:
			parambuf.event = FACE_EVENT_START_VERIFY;
			break;

			//验证删除
		case OPERATE_ID_VERIFY_DELETE:
			parambuf.event = FACE_EVENT_START_VERIFY_DELETE;
			break;

			//删除人脸
		case OPERATE_ID_DELETE:
			parambuf.event = FACE_EVENT_START_DELETE;
			break;


			//获取版本号
		case OPERATE_ID_GET_VERSION:
			parambuf.event = FACE_EVENT_GET_VERSION;
			break;

			//设置演示模式
		case OPERATE_ID_SET_DEMO_MODE:
			parambuf.event = FACE_EVENT_SET_DEMO_MODE;
			break;

			//设置工作模式
		case OPERATE_ID_SET_WORK_MODE:
			parambuf.event = FACE_EVENT_SET_WORK_MODE;
			break;

			//设置量产秘钥
		case OPERATE_ID_SET_RELEASE_ENC:
			parambuf.event = FACE_EVENT_SET_RELEASE_ENC_KEY;
			break;
		
		default:
			break;
	}

	//根据当前模式选择处理
	Face_Mode_SeletDeal(&parambuf);
}

/************************************************************************************************/
/******************************  人脸推送消息选择函数    END   ***********************************/
/************************************************************************************************/

/************************************************************************************************/
/********************************  人脸功能处理函数    STATR   ***********************************/
/************************************************************************************************/
/**
  * @brief  人脸模组上电
  * @note
  */
static void Face_PowerOn_DealFun(void)
{
	FACE_MODULE_POWER_ON;
    Device_Enable(VHW_UART_FACE);
	FaceEncrypt_Set_EnFlag(0); //非加密通信
	Face_PublishMsg(FACE_ACTION_POWER_ON, 0);
	FACE_TASK_LOG("face module power on");
	faceModuleStatus.start_time = OSAL_GetTickCount();
	faceModuleStatus.timeout = FACE_POWER_ON_TIMEOUT;
}

/**
  * @brief  人脸模组下电
  * @note
  */
static void Face_PowerDown_DealFun(void)
{
	FACE_MODULE_POWER_OFF;
    Device_Disable(VHW_UART_FACE);
	Face_PublishMsg(FACE_ACTION_POWER_OFF, 0);
	faceModuleStatus.curStatus = FACE_STATUS_POWER_DOWN;
	FACE_TASK_LOG("face module power off");
}

/**
  * @brief  人脸模组加密处理
  * @note
  */
static void Face_Encryp_DealFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	static uint8_t first_flag = 0;

	switch (parambuf->event)
	{
			//上电完成或上单超时
		case FACE_EVENT_POWER_ON_READY:
		case FACE_EVENT_POWER_ON_TIMEOUT:
			//如果已产测，第一次上电和设置产测时，还是使用临时秘钥
			if ((first_flag) && (1 == Face_ReadFaceReleaseFlag()) && (faceModuleStatus.operateId != OPERATE_ID_SET_RELEASE_ENC)) //已成功发送加密逻辑序列 release 模式
			{
				//已产测，开始初始化秘钥
				__FACE_TASK_LOG("Start init encryption\r\n");
				Face_InitEncryption_Process();
			}
			else
			{
				first_flag = 1;
				//未产测，发生临时秘钥
				__FACE_TASK_LOG("Start debug encryption key\r\n");
				Sensetime_Send_DebugEncrytionKeyNum_Cmd((uint8_t *)&faceKeyIndex, FACE_KEY_SIZE);
			}
			break;

			//临时秘钥完成
		case FACE_EVENT_DEBUG_ENC_READY:
			__FACE_TASK_LOG("Start init encryption\r\n");
			Face_InitEncryption_Process();
			break;

			//随机数初始化完成
		case FACE_EVENT_INIT_ENCRYPTION_READY:
			faceModuleStatus.curStatus = FACE_STATUS_EXECUTE;
			Face_Event_Update();
			break;

		default:
			break;
	}

}

/**
  * @brief  人脸模组录入处理
  * @note
  */
static void Face_Enroll_DealFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	s_msg_reply_enroll_data *replybuf = (s_msg_reply_enroll_data *)parambuf->data;
	static uint32_t startTime;
	uint32_t currentTime = OSAL_GetTickCount();
	uint16_t user_id;

	switch (parambuf->event)
	{
			//启动录入
		case FACE_EVENT_START_ENROLL:
			Sensetime_Send_StartEnroll_CMD(faceMsgParam.startNum);
			startTime = OSAL_GetTickCount();
			break;

			//人脸信息返回
		case FACE_EVENT_NID_FACE_STATUS:
			if (OSAL_PastTime(currentTime, startTime) > FACE_REMINDER_INTERVAL) //间隔时间提醒
			{
				startTime = OSAL_GetTickCount();
				s_note_data_face *notebuf = (s_note_data_face *)parambuf->data;
				//推送人脸信息给应用层
				Face_FaceStatus_Reminder(notebuf);
			}
			break;

			//录入完成
		case FACE_EVENT_ENROLL_SUCCESS:
			user_id = (replybuf->user_id_heb << 8 ) | replybuf->user_id_leb;
			FACE_TASK_LOG("enroll result = %d, num: %d, user_id: %d\r\n", parambuf->result, faceMsgParam.startNum,user_id);
			/* 存储userid */
			Face_WriteUserId(faceMsgParam.startNum, (uint8_t *)&user_id);
			Face_Enroll_SendActionMsg(parambuf->result,faceMsgParam.startNum);
			faceModuleStatus.curStatus = FACE_STATUS_IDLE;
			Face_Event_Deal(&parambuf);
			break;

			//录入失败
		case FACE_EVENT_ENROLL_FAIL:
			Face_Enroll_SendActionMsg(parambuf->result,faceMsgParam.startNum);
			faceModuleStatus.curStatus = FACE_STATUS_IDLE;
			Face_Event_Deal(&parambuf);
			break;

			//超时
		case FACE_ENENT_TIMEOUT:
			Face_Enroll_SendActionMsg(parambuf->result,faceMsgParam.startNum);
			faceModuleStatus.curStatus = FACE_STATUS_IDLE;
			Face_Event_Deal(&parambuf);
			break;

		default:
			break;

	}
}


/**
  * @brief  人脸模组验证处理
  * @note
  */
static void Face_Verify_DealFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	s_msg_reply_verify_data *replybuf = (s_msg_reply_verify_data *)parambuf->data;
	static uint32_t startTime;
	uint32_t currentTime = OSAL_GetTickCount();

	switch (parambuf->event)
	{
			//启动验证
		case FACE_EVENT_START_VERIFY:
			Sensetime_Send_StartVerity_CMD(1);
			Face_CheckFlag_Init();
			startTime = OSAL_GetTickCount();
			break;

			//验证删除
		case FACE_EVENT_START_VERIFY_DELETE:
			Sensetime_Send_StartVerity_CMD(4);
			Face_CheckFlag_Init();
			startTime = OSAL_GetTickCount();
			break;

			//人脸信息返回
		case FACE_EVENT_NID_FACE_STATUS:
			Face_Check(parambuf->data);
			if (OSAL_PastTime(currentTime, startTime) > FACE_REMINDER_INTERVAL) //间隔时间提醒
			{
				startTime = OSAL_GetTickCount();
				s_note_data_face *replybuf = (s_note_data_face *)parambuf->data;
				//推送人脸信息给应用层
				Face_FaceStatus_Reminder(replybuf);
			}
			break;

			//验证成功
		case FACE_EVENT_VERIFY_SUCCESS:
			id_to_delete = (replybuf->user_id_heb << 8 ) | replybuf->user_id_leb;
			Face_Verify_SendActionMsg(parambuf->result,replybuf->user_name[0]);
			faceModuleStatus.curStatus = FACE_STATUS_IDLE;
			Face_Event_Deal(&parambuf);
			Face_Verify_SendActionMsg(RESULT_END,replybuf->user_name[0]);
			break;

			//验证失败,超时
		case FACE_EVENT_VERIFY_FAIL:
		case FACE_ENENT_TIMEOUT:
			parambuf->result = ((parambuf->result != RESULT_VERIFY_FAIL_REPORT) && SET == Face_Check_Result()) ? RESULT_NO_FACE : RESULT_FAIL_REPORT;	
			FACE_TASK_LOG("Verify result: %d \r\n", parambuf->result);
			Face_Verify_SendActionMsg(parambuf->result,INVALID_NUM);
			faceModuleStatus.curStatus = FACE_STATUS_IDLE;
			Face_Event_Deal(&parambuf);
			break;

		default:
			break;

	}
}


/**
  * @brief  人脸模组删除处理
  * @note
  */
static void Face_Delete_DealFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	s_msg_reply_verify_data *replybuf = (s_msg_reply_verify_data *)parambuf->data;
	static uint32_t startTime;
	uint32_t currentTime = OSAL_GetTickCount();

	switch (parambuf->event)
	{
			//启动删除
		case FACE_EVENT_START_DELETE:
			if (FACE_DELETE_ALL_NUN == faceMsgParam.endNum)
			{
				//删除全部人脸
				faceDeleteUser.userId = FACE_DELETE_ALL_NUN | (FACE_DELETE_ALL_NUN < 8);
				faceDeleteUser.userNum = FACE_DELETE_ALL_NUN;
				Sensetime_Send_Start_DelAll_CMD(); //发送删除全部人脸的消息给人脸模组
			}
			else
			{
				//按编号删除
				faceDeleteUser.userId = id_to_delete;
				faceDeleteUser.userNum = faceMsgParam.startNum;
				FACE_TASK_LOG("Delete userNum: %02d, userId: 0x%04x",faceDeleteUser.userNum,faceDeleteUser.userId);
				Sensetime_Send_Start_DelUser_CMD(faceDeleteUser.userId);
			}
			Face_CheckFlag_Init();
			startTime = OSAL_GetTickCount();
			break;

			//删除完成
		case FACE_EVENT_DELETE_FINISH:
			FACE_TASK_LOG("FACE_EVENT_DELETE_FINISH");
			Face_Delete_SendActionMsg(parambuf->result,faceDeleteUser.userNum);
			faceModuleStatus.curStatus = FACE_STATUS_IDLE;
			Face_Event_Deal(&parambuf);
			break;

			//验证失败,超时
		case FACE_EVENT_VERIFY_FAIL:
		case FACE_ENENT_TIMEOUT:
			FACE_TASK_LOG("FACE_EVENT_VERIFY_FAIL  FACE_ENENT_TIMEOUT");
			parambuf->result = ((parambuf->result != RESULT_VERIFY_FAIL_REPORT) && SET == Face_Check_Result()) ? RESULT_NO_FACE : RESULT_FAIL_REPORT;	
			Face_Delete_SendActionMsg(parambuf->result,faceDeleteUser.userNum);
			faceModuleStatus.curStatus = FACE_STATUS_IDLE;
			Face_Event_Deal(&parambuf);
			break;


		default:
			break;

	}


}

/**
  * @brief  人脸模组终止处理
  * @note
  */
static void Face_Idle_DealFun(Face_DealParam_stu_t *param)
{
	Sensetime_Send_Reset_CMD(); //发送终止当前操作指令（验证、注册）
	faceModuleStatus.curStatus = FACE_STATUS_SLEEPED;
	faceModuleStatus.operateId = OPERATE_ID_MAX;
}

/**
  * @brief  人脸模组睡眠处理
  * @note
  */
static void Face_Sleep_DealFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;

	switch (parambuf->event)
	{
			//终止操作完成
		case FACE_EVENT_ABORT_FINISH:
			Sensetime_Send_GetAllUserid_CMD();
			break;

			//获取所有注册用户
		case FACE_EVENT_GET_ALL_USERID:
			Face_PowerDown_DealFun();		//直接下电
			break;

			//模组存在多余id，删除完成
		case FACE_EVENT_DELETE_FINISH:
			Sensetime_Send_GetAllUserid_CMD();
			break;

			//模组睡眠完成
		case FACE_EVENT_SLEEP_FINISH:
			Face_PowerDown_DealFun();
			break;

			//超时
		default:
			Face_PowerDown_DealFun();
			break;		
	}
}

/**
  * @brief  人脸模组设置完成处理
  * @note
  */
static void Face_SettingFinish_Process(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;

	switch(parambuf->result)
	{
		case RESULT_SUCCESS_REPORT:
			
			if(faceModuleStatus.operateId == OPERATE_ID_SET_RELEASE_ENC)
			{
				//设置量产标志位
				Face_SetFaceReleaseFlag(1);
				Face_PublishMsg(FACE_ACTION_ENC_SUCCESS,INVALID_NUM);
			}

			break;

		case RESULT_ENCRYPTED:
			//设置量产标志位
			Face_SetFaceReleaseFlag(1);
			Face_PublishMsg(FACE_ACTION_ENC_SUCCESS,INVALID_NUM);
			break;

		default:
			break;

	}

	faceModuleStatus.curStatus = FACE_STATUS_IDLE;
	Face_Event_Deal(&parambuf);
}

/**
  * @brief  人脸模组设置
  * @note
  */
static void Face_Setting_DealFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	FaceActionType_enum_t action = FACE_ACTION_MAX;


	switch (parambuf->event)
	{
			//获取版本号
		case FACE_EVENT_GET_VERSION:
			Sensetime_Send_Get_Version_CMD();
			break;

			//设置演示模式
		case FACE_EVENT_SET_DEMO_MODE:
			Sensetime_Send_SetDemoMode_CMD(0x01);
			break;

			//设置工作模式
		case FACE_EVENT_SET_WORK_MODE:
			Sensetime_Send_SetDemoMode_CMD(0x00);
			break;

			//设置量产秘钥
		case FACE_EVENT_SET_RELEASE_ENC_KEY:
			Sensetime_Send_ReleaseEncrytionKeyNum_Cmd((uint8_t *)&faceKeyIndex, FACE_KEY_SIZE);
			break;

			//设置完成
		case FACE_EVENT_SET_FINISH:
			Face_SettingFinish_Process(param);
			break;

			//超时
		case FACE_ENENT_TIMEOUT:
			action = FACE_ACTION_TIME_OUT;
			Face_PublishMsg(action,INVALID_NUM);
			Face_PowerDown_DealFun();
			break;

		default:
			action = FACE_ACTION_TIME_OUT;
			Face_PublishMsg(action,INVALID_NUM);
			Face_PowerDown_DealFun();
			break;

	}
}

/**
  * @brief  人脸模组OTA
  * @note
  */
static void Face_Ota_DealFun(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;
	FaceActionType_enum_t action = FACE_ACTION_MAX;

	switch (parambuf->event)
	{
			//启动升级
		case FACE_EVENT_START_OTA:
			Sensetime_Send_StartOta_CMD();
			break;

			//OTA已启动
		case FACE_EVENT_OTA_READY:
			Sensetime_Send_GetOtaStatus_CMD();
			break;

			//获取完成OTA状态
		case FACE_EVENT_OTA_STATUS_FINISH:
			action = FACE_ACTION_ENTER_OTA_MODE;
			Face_PublishMsg(action,INVALID_NUM);
			break;

			//OTA完成
		case FACE_EVENT_OTA_FINISH:
			Face_Ota_SendActionMsg(parambuf->result,INVALID_NUM);
			break;

		default:
			break;

	}
}


static void Face_Mode_Update(Face_operate_id_enum_t msgId)
{
	Face_operate_id_enum_t opeId = msgId;
	

	switch(opeId)
	{
		case OPERATE_ID_ENROLL:
			faceModuleStatus.curMode = FACE_MODULE_ENROLL_MODE;
			break;

		case OPERATE_ID_VERIFY:
		case OPERATE_ID_VERIFY_DELETE:
			faceModuleStatus.curMode = FACE_MODULE_VERIFY_MODE;
			break;

		case OPERATE_ID_DELETE:
			faceModuleStatus.curMode = FACE_MODULE_DELETE_MODE;
			break;

		case OPERATE_ID_ABORT:
			faceModuleStatus.curMode = FACE_MODULE_IDLE_MODE;
			break;

		case OPERATE_ID_SET_RELEASE_ENC:
			faceModuleStatus.curMode = FACE_MODULE_SET_MODE;
			break;

		case OPERATE_ID_START_OTA:
			faceModuleStatus.curMode = FACE_MODULE_OTA_MODE;
			break;

		case OPERATE_ID_SET_DEMO_MODE:
		case OPERATE_ID_SET_WORK_MODE:
		case OPERATE_ID_GET_VERSION:
			faceModuleStatus.curMode = FACE_MODULE_SET_MODE;
			break;
		
	}
	FACE_TASK_LOG("update cur mode: %d\r\n",faceModuleStatus.curMode);

}



/**
  * @brief  人脸模式选择处理
  *
  * @note
  */
static void Face_Mode_SeletDeal(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;

	FACE_TASK_LOG("selet curMode :%d, event: %d, result :%d",faceModuleStatus.curMode,parambuf->event,parambuf->result);
	switch (faceModuleStatus.curMode)
	{
			//验证
		case FACE_MODULE_VERIFY_MODE:
			Face_Verify_DealFun(parambuf);
			break;

			//录入
		case FACE_MODULE_ENROLL_MODE:
			Face_Enroll_DealFun(parambuf);
			break;
			
			//删除
		case FACE_MODULE_DELETE_MODE:
			Face_Delete_DealFun(parambuf);
			break;

			//OTA
		case FACE_MODULE_OTA_MODE:
			Face_Ota_DealFun(parambuf);
			break;

			//设置模式
		case FACE_MODULE_SET_MODE:
			Face_Setting_DealFun(parambuf);
			break;
		
		
		default:
			break;
	}

}




ErrorStatus MasterOperate_ReadRingBuff(void)
{
	Face_Param_stu_t parambuf;

	if (OSAL_RingBufferRead(MasterOperate_rbHandle, &parambuf) == SUCCESS)
	{
		FACE_TASK_LOG("master read actionId %d",parambuf.actionId);
		faceModuleStatus.operateId = parambuf.actionId;
		faceMsgParam.actionId = parambuf.actionId;
		faceMsgParam.startNum = parambuf.startNum;
		faceMsgParam.endNum = parambuf.endNum;

		faceModuleStatus.curStatus = FACE_STATUS_EXECUTE;
		Face_Mode_Update(parambuf.actionId);
		Face_Event_Update();

		return SUCCESS;
	}

	return ERROR;
}


/**
  * @brief  API操作写入队列
  * @param  msgId:消息id
  * 
  * @note   
  * 		
  */
static ErrorStatus MasterOperate_WriteRingBuff(Face_operate_id_enum_t msgId, uint8_t param1, uint8_t param2)
{
	Face_Param_stu_t data;
	data.actionId = msgId;
	data.startNum = param1;
	data.endNum = param2;
	FACE_TASK_LOG("write master msg to ringbuff");

	if (MasterOperate_rbHandle != NULL)
	{
		if (ERROR == OSAL_RingBufferWrite(MasterOperate_rbHandle, &data))
		{
			FACE_TASK_LOG("write master msg to face ring fail");
		}
	}
}




/**
  * @brief  人脸控制流程
  * @param  msgId:消息id
  * @param  param1:参数1
  * @param  param2:参数2
  * 
  * @note   
  * 		
  */
static ErrorStatus Face_Ctrl(Face_operate_id_enum_t msgId, uint8_t param1, uint8_t param2)
{
	FACE_TASK_LOG("msgid: %d, startNum: %d, endNum: %d",msgId,param1,param2);
	FACE_TASK_LOG("curstatus: %d\r\n",faceModuleStatus.curStatus);

	switch(faceModuleStatus.curStatus)
	{
			//状态：断电
		case FACE_STATUS_POWER_DOWN:
			if(msgId != OPERATE_ID_ABORT)
			{
				//上电启动
				faceModuleStatus.curStatus = FACE_STATUS_POWER_ON;
				Face_PowerOn_DealFun();
			}
			else
			{
				return ERROR;
			}
			
			break;

		case FACE_STATUS_POWER_ON:
			if(msgId != OPERATE_ID_ABORT)
			{
				MasterOperate_WriteRingBuff(msgId,param1,param2);
				return SUCCESS;
			}
			else if((faceModuleStatus.operateId == OPERATE_ID_DELETE) && (msgId == OPERATE_ID_ABORT))
			{
				return ERROR;
			}
			else
			{
				faceModuleStatus.timeout = FOREVER_TIME_OUT;
				Face_PowerDown_DealFun();
				return SUCCESS;
			}
			break;

		case FACE_STATUS_ENCRYPTION:
		case FACE_STATUS_EXECUTE:
			if(msgId == OPERATE_ID_ABORT && (faceModuleStatus.operateId != OPERATE_ID_DELETE))
			{
				//终止操作
				faceModuleStatus.curStatus = FACE_STATUS_IDLE;
				Sensetime_Send_Reset_CMD();
			}
			else if(msgId == OPERATE_ID_DELETE || (msgId == OPERATE_ID_VERIFY) || (msgId == OPERATE_ID_VERIFY_DELETE))
			{
				MasterOperate_WriteRingBuff(msgId,param1,param2);
				return SUCCESS;
			}

			break;

		case FACE_STATUS_IDLE:
			if (msgId == OPERATE_ID_DELETE || msgId == OPERATE_ID_VERIFY || OPERATE_ID_VERIFY_DELETE)
			{
				MasterOperate_WriteRingBuff(msgId,param1,param2);
			}
			break;
		
		case FACE_STATUS_SLEEPED:
			if(msgId != OPERATE_ID_ABORT)
			{
				MasterOperate_WriteRingBuff(msgId,param1,param2);
				//faceModuleStatus.curStatus = FACE_STATUS_EXECUTE;
				//Face_Event_Update();
				return SUCCESS;
			}
			
			break;

		default :
			break;
	}

	FACE_TASK_LOG("msgid2: %d",msgId);
	Face_Mode_Update(msgId);
	faceModuleStatus.operateId = msgId;
	faceMsgParam.actionId = msgId;
	faceMsgParam.startNum = param1;
	faceMsgParam.endNum = param2;

	
	return SUCCESS;
}

/**************************************API接口   START*************************************************/

/**
  * @brief  当前人脸模组模式
  * @note
  */
static Face_mode_enum_t Face_Get_FaceModule_CurMode(void)
{
	return faceModuleStatus.curMode;
}

/**
  * @brief  API:结束当前人脸模组的操作（验证、录入）
  * @note   
  */
static ErrorStatus Face_Abort_Current_Operation(void)
{
	FACE_TASK_LOG("Master request abort");
	return Face_Ctrl(OPERATE_ID_ABORT, 0, 0);
}

/**
  * @brief  API:认证人脸 verify 
  * @note   该函数命名单词拼错了
  */
static ErrorStatus Face_Verity_Start(void)
{
	FACE_TASK_LOG("Master request verity");
	return Face_Ctrl(OPERATE_ID_VERIFY, 0, 0);
}

/**
  * @brief  API:录入人脸      
  * @param enroll_num 录入编号
  * 
  */
static ErrorStatus Face_Enroll_Start(uint8_t enrollNum)
{
	FACE_TASK_LOG("Master request enroll");
	Face_Ctrl(OPERATE_ID_ENROLL, enrollNum, 0);
	return SUCCESS;
}

/**
  * @brief  API:删除人脸前先验证
  * @note   
  */
static ErrorStatus Face_Delete_Verity_Start(void)
{
	FACE_TASK_LOG("Master request verity delete");
	return Face_Ctrl(OPERATE_ID_VERIFY_DELETE, 0, 0);
}

/**
  * @brief  API:删除人脸
  * @param  startNum:删除的起始编号
  * @param  endNum:删除的结束编号
  *  
  * @note   endNum  == 0xFF 为删除全部    startNum为起始的删除编号
  * 		endNum ！= 0xFF 为单个删除    startNum ~ endNum 为允许删除的编号范围。
  * 	   
  */

static ErrorStatus Face_Delete_Start(uint8_t startNum, uint8_t endNum)
{
	FACE_TASK_LOG("Master request delete(%d, %d)", startNum, endNum);
	/* 直接删除本地索引 */
	if(FACE_DELETE_ALL_NUN == endNum) //删除全部
	{
		Face_DeleteAllIndex();
	}
	else //删除单个
	{
		Face_ReadUserId(startNum, (uint8_t *)&id_to_delete);
		Face_DeleteIndex(startNum);
	}
	return Face_Ctrl(OPERATE_ID_DELETE, startNum, endNum);
}

/**
  * @brief  人脸任务 OTA 启动
  * @note        
  * @param num : 0x00  启动人脸模组算法库升级
  * 			 0x01  启动人脸模组应用层升级
  * @param 
  */
static ErrorStatus Face_OTA_Start(void)
{
	FACE_TASK_LOG("Master request start face ota");
	Face_Ctrl(OPERATE_ID_START_OTA, 0, 0);
	return SUCCESS;
}

/**
  * @brief  设定量产加密的秘钥	
  * @note   
  */
static ErrorStatus Face_Set_Enc_Key(void)
{
	FACE_TASK_LOG("Master requset set face enc ");
	Face_Ctrl(OPERATE_ID_SET_RELEASE_ENC, 0, 0);
	return SUCCESS;
}

/**
  * @brief  人脸恢复出厂设置	
  * @note   
  */
static ErrorStatus Face_Factory(void)
{
	FACE_TASK_LOG("Master ask factory");
	NvFace_stu_t nv_face;
	int len = sizeof(NvFace_stu_t) - sizeof(nv_face.faceReleaseFlag);
	memset(&nv_face.faceSn, 0xff, len);
	OSAL_NvWrite(OSAL_OFFSET(NvFace_stu_t, faceSn), &nv_face.faceSn, len);
	return SUCCESS;
}

/**
  * @brief  人脸任务	设置为演示模式
  * @param mode:   1: 进入演示模式
  * 			   0: 退出演示模式
  *  
  * @note   
  */
static ErrorStatus Face_Set_Demo_Mode(uint8_t mode)
{
	FACE_TASK_LOG("Master set face demo mode ");
	Face_operate_id_enum_t msgId = mode ? OPERATE_ID_SET_DEMO_MODE : OPERATE_ID_SET_WORK_MODE;
	return Face_Ctrl(msgId, 0, 0);
}

/***************************************************************************************************/
/*********************************    API接口   END     ********************************************/
/***************************************************************************************************/

/**
  * @brief  人脸任务	读取版本号	   
  */
static ErrorStatus Face_Get_Version(void)
{
	FACE_TASK_LOG("get version ");
	return Face_Ctrl(OPERATE_ID_GET_VERSION, 0, 0);
}



/**
  * @brief  人脸事件处理
  * @param  param:处理参数结构体
  * 
  * @note   
  * 		
  */
void Face_Event_Deal(Face_DealParam_stu_t *param)
{
	Face_DealParam_stu_t *parambuf = param;

	switch (faceModuleStatus.curStatus)
	{
			//上电，加密
		case FACE_STATUS_POWER_ON:
		case FACE_STATUS_ENCRYPTION:
			Face_Encryp_DealFun(parambuf);
			break;

			//执行中
		case FACE_STATUS_EXECUTE:
			Face_Mode_SeletDeal(parambuf);
			break;

			//空闲
		case FACE_STATUS_IDLE:
			Face_Idle_DealFun(parambuf);
			break;

			//睡眠
		case FACE_STATUS_SLEEPED:
			if(MasterOperate_ReadRingBuff() != SUCCESS)
			{
				Face_Sleep_DealFun(parambuf);
			}
			break;

		case FACE_STATUS_OTA:
			break;

		default:
			break;
	}
}


/*********************************************************************************************/
/************************************发送和接收数据结构体定义START***************************************/
#define PROTOCOL_STX 0xEFAA //帧数据头

#define PACK_TYPE_CONFRIM 0X00 //应答包类型：确认包
#define PACK_TYPE_ACK 0X01	   //应答包类型：应答包

/*功能函数宏定义*/
#define CHECK_SUM_DATA_START 2          //校验和计算起始字节相对帧首字节偏移
#define CHECK_SUN_LEN_ADD 3	            //校验和计算长度相对帧长度增加的个数

#define MAX_TX_PACKAGE_LEN            64          //最大包长
#define MAX_RX_PACKAGE_LEN            128          //最大包长

#pragma pack(1)
/*帧头数据结构*/
typedef struct
{
	uint16_t stx;  //帧头同步字
	uint8_t msgID; //消息ID
	uint16_t len;  //data数据长度
} ProtocolDataHead_stu_t;

/*加密帧头数据结构*/
typedef struct
{
	uint16_t stx;	//帧头同步字
	uint16_t len;	//data数据长度
	uint8_t data[]; //命令
} ProtocolDataHeadEncrypt_stu_t;

/*帧数据结构*/
typedef struct
{
	ProtocolDataHead_stu_t head; //帧头结构体
	uint8_t data[];				 //命令
} CmdPacket_stu_t;

/*M:模组
 *H:主控*/
/*M->H reply 模块对主控的应答data结构解析 msgID为0x00*/
typedef struct
{
	uint8_t r_msgID;  //应答对应的消息ID和命令的msg_ID 对应
	uint8_t result;	  //应答结果
	uint8_t r_data[]; //应答数据缓存
} Reply_data_stu_t;

/*note数据的结构*/
typedef struct
{
	uint8_t n_msgID;  //note ID
	uint8_t n_data[]; //note 数据缓存
} Note_data_stu_t;
#pragma pack()

//发送包信息
static struct
{
	uint8_t dataBuf[MAX_TX_PACKAGE_LEN];      //当前发送的整包数据
	uint16_t dataLen;		//当前发送数据的总长度

	uint8_t cmd;			 //msgid
	uint8_t cnt;			 //
	FlagStatus waitAckFlag;	 //等待ack标志位
	uint32_t timeStamp;		 //时间戳
	uint32_t waitAckTimeout; //等待超时时间
	enum
	{					 
		TX_STA_IDLE,	  
		TX_STA_WAIT_ACK, 
        TX_STA_WAIT_NEXT
	} status;
} CmdPacketTxInfo;

//接收包信息
static struct
{
	uint8_t protocolBuf[MAX_RX_PACKAGE_LEN]; 	//协议buff
	uint8_t protocolCount;				  		//协议计数

} CmdPacketRxInfo;

#define FACE_TX_CMD_BUFF_NUM 5	   //发送命令环形队列深度

static RingBufferHandle_t FaceTxCmd_rbHandle = NULL; /* 发送循环队列句柄 */



/*************************************发送和接收数据结构体定义END**************************************/
/****************************************************************************************************/
/*************************************发送操作相关函数 START******************************************/

static void Face_PrintfTxData(uint8_t *pData, uint16_t len)
{
#if defined(DEBUG_EN)
	uint8_t strBuffer[66 * 3], i;
	if (len > 65)
		return; //格式化数组数量不能超过66*3
	for (i = 0; i < len; i++)
	{
		sprintf((char *)&strBuffer[i * 3], "%02X ", pData[i]);
	}
	sprintf((char *)&strBuffer[i * 3], "%s", "\r\n\r\n");
	FACE_TASK_LOG("FaceTask send packet:%s", strBuffer);
#endif
}

/**
  * @brief  校验和
  * @note
  *
  * @param  pData: 数据指针
  * @param  len: 数据长度
  * @return 数据异或校验和:
  * 		非加密数据：除帧头（EF AA）和最后一个校验和以外的所有字节都需要计算
  * 		加密数据：除帧头（EF AA）、 长度（从0开始算，第2、3个字节）和最后一个校验和以外的所有字节都需要计算
  */
static uint8_t Face_CalcCheckSum(uint8_t *pData, uint16_t len)
{
	uint8_t sum = 0;
	//FACE_TASK_DEBUG_LOG("check sum:");
	for (; len; len--)
	{
		//FACE_TASK_DEBUG_LOG("%#2x ",*pData);
		sum ^= *pData++;
	}
	//FACE_TASK_DEBUG_LOG("\r\n");
	return sum;
}


/**
  * @brief  加载待发送的数据
  * @note   将要发出的数据，填入发送缓存区
  *
  * @param  pData：数据指针
  * @param  len：数据长度
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus Face_LoadingDataToBeSent(uint8_t *pData, uint16_t len)
{
	if (len > 0x7FFF) //直接发
	{
		len &= 0x7FFF;
		Face_PrintfTxData(pData, len);
		Device_Write(VHW_UART_FACE, pData, len, 0);
		return SUCCESS;
	}
	return ERROR;
}


/**
  * @brief  人脸模块 数据打包
  * @note   
  *
  * @param  cmd：消息id
  * @param  pData：数据
  * @param  dataLen：数据长度
  * @param  waitAckFlag：等待回复标志
  * @return 成功返回SUCCESS，失败返回ERROR
  */
static ErrorStatus Face_SendPacket(uint8_t cmd, uint8_t *pData, uint16_t dataLen, FlagStatus waitAckFlag)
{
    CmdPacket_stu_t *pCmdPacket = (CmdPacket_stu_t *)CmdPacketTxInfo.dataBuf;
    ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)CmdPacketTxInfo.dataBuf; //加密模式帧头数据结构
	uint8_t encryptData[64] = {0};
	uint16_t encryptDataLen;
	uint16_t encryptInputLen;
    ErrorStatus re;

    //memset(&CmdPacketTxInfo,0,sizeof(CmdPacketTxInfo));
    CmdPacketTxInfo.cmd = cmd;
	CmdPacketTxInfo.waitAckFlag = waitAckFlag;
	CmdPacketTxInfo.cnt = 1;
	CmdPacketTxInfo.status = TX_STA_WAIT_ACK;
	CmdPacketTxInfo.timeStamp = OSAL_GetTickCount();

    //数据打包
    pCmdPacket->head.stx = PROTOCOL_STX;
	pCmdPacket->head.stx = SWAP16(pCmdPacket->head.stx); //大小端转化
	pCmdPacket->head.msgID = cmd;
	pCmdPacket->head.len = dataLen;						 //data长度
	pCmdPacket->head.len = SWAP16(pCmdPacket->head.len); //大小端转化
	memcpy(pCmdPacket->data, pData, dataLen);

    //FACE_TASK_LOG("tx cmd: %x,len: %d",cmd,dataLen);

    pCmdPacket->data[dataLen] = Face_CalcCheckSum((uint8_t *)&(pCmdPacket->head.stx) + CHECK_SUM_DATA_START, dataLen + CHECK_SUN_LEN_ADD);
	CmdPacketTxInfo.dataLen = sizeof(CmdPacket_stu_t) + dataLen + 1;

    //开启OTA指令需要加密
    if(1 == FaceEncrypt_Get_EnFlag())
    {
        //FACE_TASK_LOG("encrypt packet: %d",strlen(CmdPacketTxInfo.dataBuf));

        CmdPacketTxInfo.dataLen = dataLen + 5;
		Face_PrintfTxData(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen); //仿真模式打印出加密前的数据
																			 //#endif
		pPacketHeadEncrypt->stx = PROTOCOL_STX;
		pPacketHeadEncrypt->stx = SWAP16(pPacketHeadEncrypt->stx); //大小端转化
		encryptInputLen = dataLen + 3;      //数据内容 + msgid(1) + len(2)

        //数据加密
		FaceEncrypt_SenseTime_Encrypt_Decrypt(1, (uint8_t *)&pCmdPacket->head.msgID, &encryptInputLen, encryptData, &encryptDataLen);

		memcpy(pPacketHeadEncrypt->data, encryptData, encryptDataLen);  //加密数据赋值
		pPacketHeadEncrypt->len = encryptDataLen;

		pPacketHeadEncrypt->data[encryptDataLen] = Face_CalcCheckSum((uint8_t *)pPacketHeadEncrypt->data, encryptDataLen);
		CmdPacketTxInfo.dataLen = sizeof(ProtocolDataHeadEncrypt_stu_t) + encryptDataLen + 1;
		pPacketHeadEncrypt->len = SWAP16(pPacketHeadEncrypt->len); //大小端转化

    }

    //发送数据
    re = Face_LoadingDataToBeSent(CmdPacketTxInfo.dataBuf, CmdPacketTxInfo.dataLen | 0x8000);
    FACE_TASK_LOG("tx status: %d",CmdPacketTxInfo.status);

	if (cmd == MID_INIT_ENCRYPTION)
	{
		FaceEncrypt_Set_EnFlag(1); //启动加密通信
	}
	else if (cmd == MID_START_OTA)
	{
		FaceEncrypt_Set_EnFlag(0); //关闭加密通信
	}

    return re;
}


/**
  * @brief  人脸模组发送数据写入队列 H->M
  * @note   调用此函数时不是立马发送，而是暂存到环形缓存里面
  * @param  pData:发送数据
  */
void Face_TxCmdRingBuffWrite(SensetimeTxCmdMsg_stu_t *pData)
{
	if (FaceTxCmd_rbHandle != NULL)
	{
		OSAL_RingBufferWrite(FaceTxCmd_rbHandle, pData);
	}
}


/**
  * @brief 处理人脸发送和设置缓存数据
  *
  * @note  
  */
static void Face_SendRingBuffDataProcess(void)
{
	if (OSAL_RingBufferGetValidSize(FaceTxCmd_rbHandle) != 0)
	{
		FlagStatus ackFlag;
		SensetimeTxCmdMsg_stu_t Data = {0};
		OSAL_RingBufferRead_No_Clear(FaceTxCmd_rbHandle, &Data);

		if ((Data.msgID == MID_RESET && FACE_MODULE_SLEEPED_MODE != Face_Get_FaceModule_CurMode())
				|| (CmdPacketTxInfo.status == TX_STA_IDLE)) // 在非休眠状态下发重置命令立即执行,或者在发送空闲时执行
		{

			if (OSAL_RingBufferRead(FaceTxCmd_rbHandle, &Data) == SUCCESS)
			{
				if (Data.cb != NULL)
				{
					ackFlag = SET;
					//指令对应回复的回调进行赋值
					pCmdCallback = Data.cb;
					CmdPacketTxInfo.waitAckTimeout = Data.timeout;
				}
				else
				{
					ackFlag = RESET;
				}
				Face_SendPacket(Data.msgID, Data.dataBuf, Data.data_len, ackFlag);
				FACE_TASK_LOG("RingBuff_Tx_OK msgID = 0X%2X\r\n", Data.msgID);
			}
		}
	}

}


/***********************************发送操作相关函数 END**************************************************/
/********************************************************************************************************/

/**
  * @brief  从底层环形缓存获取一包数据并解析
  *
  * @note   底层驱动收到数据，会暂存在环形缓存区
  *
  * @return 返回解析后的数据包地址，解析失败返回NULL
  */
static uint8_t *Face_GetOnePacket(void)
{
	static uint8_t getPacketTimeoutCnt = 0;
    uint8_t *protocolBuff = NULL;               //解析的buff
    uint8_t *pCnt = NULL;                       
	uint8_t sum = 0;
	uint16_t packetLen = 0;                     //整包长度
	uint8_t tmpData;                            //缓冲变量，从缓冲区读数据
	uint32_t tmpLen = 0;
    ProtocolDataHead_stu_t *pPacketHead = NULL;
    ProtocolDataHeadEncrypt_stu_t *pPacketHeadEncrypt = NULL; //加密模式帧头数据结构

	uint8_t decryptData[MAX_RX_PACKAGE_LEN] = {0};
    uint8_t buff[64];
	uint16_t decryptDataLen;

    //查询缓冲区是否有数据
	tmpLen = OSAL_RingBufferGetValidSize(uartFace_rbHandle);
	if (tmpLen == 0)
	{
		/* 连续3次没有读取到数据（30ms） */
		if (++getPacketTimeoutCnt >= 3)
		{
			if(CmdPacketRxInfo.protocolCount)
			{
				FACE_TASK_LOG("face recv timeout\r\n");
			}
			getPacketTimeoutCnt = 0;
			CmdPacketRxInfo.protocolCount = 0; //清0解析计数
		}
		return NULL;
	}

    //FACE_TASK_LOG("face get pack len:%d",tmpLen);
    pCnt = &(CmdPacketRxInfo.protocolCount);	//解析计数
    protocolBuff = CmdPacketRxInfo.protocolBuf; //解析缓存
    pPacketHead = (ProtocolDataHead_stu_t *)protocolBuff;
    pPacketHeadEncrypt = (ProtocolDataHeadEncrypt_stu_t *)protocolBuff;
    //循环读字节
    for (; tmpLen; tmpLen--)
	{
		OSAL_RingBufferRead(uartFace_rbHandle, &tmpData); //读取到一个字节数据
        //FACE_TASK_LOG("tmpdata %02x\r\n",tmpData);
        if(*pCnt == 0)
        {
            if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
            {
                protocolBuff[0] = tmpData;
                //FACE_TASK_LOG("PROTOCOL_STX head ok");
                //FACE_TASK_LOG(" %02X", protocolBuff[*pCnt]);
                *pCnt = 1;
                
            }
        }
        else if(*pCnt == 1)
        {
            if (tmpData == (PROTOCOL_STX & 0x00FF)) //帧数据头低字节
			{
				protocolBuff[1] = tmpData;
                //FACE_TASK_LOG(" %02X", protocolBuff[*pCnt]);
				*pCnt = 2;
			}
            else if (tmpData == ((PROTOCOL_STX >> 8) & 0x00FF)) //帧数据头高字节
			{


            }
            else
            {
                *pCnt = 0;
            }
        }
        else if(*pCnt > 1)
        {
            protocolBuff[*pCnt] = tmpData;
            *pCnt = *pCnt + 1;
            //FACE_TASK_LOG("%02X", protocolBuff[*pCnt]);
            //非加密
            if(FaceEncrypt_Get_EnFlag() == 0)
            {
                if(*pCnt == 5)
                {
                    //FACE_TASK_LOG("1 len %04x, %04x", pPacketHead->len,pPacketHead->stx);
                    pPacketHead->len = SWAP16(pPacketHead->len); //大小端转化
					pPacketHead->stx = SWAP16(pPacketHead->stx); //大小端转化
                    FACE_TASK_LOG("rx len %04x, %04x", pPacketHead->len,pPacketHead->stx);
                }
                else if(*pCnt > 5)
                {
                    packetLen = pPacketHead->len + 6;  //包总长，data + 包头(2) + msgid(1) + datalen(2) + checksum(1)
                    if(packetLen == *pCnt)
                    {
                        sum = Face_CalcCheckSum(protocolBuff + CHECK_SUM_DATA_START, pPacketHead->len + CHECK_SUN_LEN_ADD);

                        if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
						{
                            FACE_TASK_LOG("RECEIVE RIGHT:");
                            for (int i = 0; i < packetLen; i++)
                            {
                                __FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
                            }
                            __FACE_TASK_DEBUG_LOG("\r\n");
                            *pCnt = 0;
                            return protocolBuff;
                        }
                        else
                        {
                            FACE_TASK_LOG("CRC ERR:");
                            for (int i = 0; i < packetLen; i++)
                            {
                                __FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
                            }
                            __FACE_TASK_DEBUG_LOG("\r\n");
                        }
                        
                        *pCnt = 0;
                        return NULL;
                        
                    }
                    else
                    {
                        //FACE_TASK_LOG("packetLen: %02x,%02x",*pCnt,packetLen);
                    }
                }
            }
            else
            {
                if (*pCnt == 4)
				{
                    //FACE_TASK_LOG("1 encrypt len: %02x",pPacketHeadEncrypt->len);
					pPacketHeadEncrypt->len = SWAP16(pPacketHeadEncrypt->len); //大小端转化
					pPacketHeadEncrypt->stx = SWAP16(pPacketHeadEncrypt->stx); //大小端转化
                    //FACE_TASK_LOG("rx encrypt len: %02x",pPacketHeadEncrypt->len);
				}
				if (*pCnt > 4)
				{
					packetLen = pPacketHeadEncrypt->len + 5;
					if (*pCnt >= MAX_RX_PACKAGE_LEN || packetLen == *pCnt)
					{
						if (packetLen == *pCnt)
						{
							sum = Face_CalcCheckSum(pPacketHeadEncrypt->data, pPacketHeadEncrypt->len);
							if (protocolBuff[packetLen - 1] == sum) //最后一个字节位校验和
							{
                                
								FaceEncrypt_SenseTime_Encrypt_Decrypt(0, pPacketHeadEncrypt->data, &pPacketHeadEncrypt->len, decryptData, &decryptDataLen);
								memcpy(&pPacketHeadEncrypt->len, decryptData, decryptDataLen);
								pPacketHead->len = SWAP16(pPacketHead->len); //大小端转化
								FACE_TASK_LOG("RECEIVE RIGHT: %02x",pPacketHead->len);
								for (int i = 0; i < packetLen; i++)
								{
									__FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__FACE_TASK_DEBUG_LOG("\r\n");
								*pCnt = 0;

								if ((pPacketHead->len + 6) <= MAX_RX_PACKAGE_LEN)
								{
									return protocolBuff;
								}
								else
								{
									FACE_TASK_LOG("LEN ERR\r\n");
								}
							}
							else
							{
								FACE_TASK_LOG("CRC ERR:");
								for (int i = 0; i < packetLen; i++)
								{
									__FACE_TASK_DEBUG_LOG(" %02X", protocolBuff[i]);
								}
								__FACE_TASK_DEBUG_LOG("\r\n");
							}
						}
						else
						{
							FACE_TASK_LOG("packet err\r\n");
						}
						*pCnt = 0;
						return NULL;
					}
                    else
                    {
                        //FACE_LOG("packetLen: %02x,%02x",*pCnt,packetLen);
                    }
				}
            }

        }

    }
	
	return NULL;
}




/**
  * @brief  处理应答reply包结果
  * @note
  *
  * @param  pAckPacket：包内容
  */
static void Face_Reply_PacketResult(CmdPacket_stu_t *pAckPacket)
{
	Reply_data_stu_t *replyData = (Reply_data_stu_t *)pAckPacket->data;

	if (replyData->r_msgID == CmdPacketTxInfo.cmd)
	{
		FACE_TASK_LOG("Callback CMD=%#2X\r\n", replyData->r_msgID);
		if (pCmdCallback != NULL)
		{
			//各指令的对应reply的回调函数进行处理
			pCmdCallback(replyData->result, replyData->r_data, pAckPacket->head.len - 2);
			pCmdCallback = NULL;
		}
		CmdPacketTxInfo.status = TX_STA_IDLE;
	}
}

/**
  * @brief  处理note包的结果
  * @note   模块的状态包括：IDLE(0),BUSY(1),ERROR(2),INVALID(3) OTA进行中(4)
  *
  * @param  pCmdPacket: 包数据
  */
static void Face_Note_PacketResult(CmdPacket_stu_t *pCmdPacket)
{
	Note_data_stu_t *noteData = (Note_data_stu_t *)pCmdPacket->data;

	switch (noteData->n_msgID)
	{
			//开机准备好了
		case NID_READY:
			faceModuleStatus.timeout = FOREVER_TIME_OUT;
			Sensetime_Nid_Ready();
			break;

			//人脸信息返回
		case NID_FACE_STATE:
			Sensetime_Nid_Face_Status(noteData->n_data);
			break;

			//OTA结果
		case NID_OTA_DONE:
			Sensetime_Nid_Ota_Done(noteData->n_data);
			break;
		
		default:
			break;
	}

}

/**
  * @brief  解析读取的数据包
  * @note
  *
  * @param  pData:数据包
  */
static void Face_ParseRxPacket(uint8_t *pData)
{
	CmdPacket_stu_t *pPacketHead = (CmdPacket_stu_t *)pData;

    if (pPacketHead->head.msgID == FACE_MID_REPLY) //处理reply消息
    {
        FACE_TASK_LOG("reply pack");
        Face_Reply_PacketResult((CmdPacket_stu_t *)pData);
        
    }

    else if (pPacketHead->head.msgID == FACE_MID_NOTE) //处理note消息
    {
        FACE_TASK_LOG("note pack");
        Face_Note_PacketResult((CmdPacket_stu_t *)pData);
        
    }
    
}

/**
  * @brief  重发指令包
  *
  * @note   
  */
static void Face_ResendCmdPacket(void)
{
	uint32_t currentTime = OSAL_GetTickCount();
	uint8_t ret = ACK_RES_TIMEOUT;
	Face_DealParam_stu_t DealParam;

	if (CmdPacketTxInfo.status == TX_STA_WAIT_ACK) //当前状态正在等应答
	{
		if (OSAL_PastTime(currentTime, CmdPacketTxInfo.timeStamp) > CmdPacketTxInfo.waitAckTimeout)
		{
			//ERR:超时
			FACE_TASK_LOG("wait ack Time out cmd = %#2x,%#2x,%#2x,%#2x", CmdPacketTxInfo.cmd, currentTime, CmdPacketTxInfo.timeStamp, CmdPacketTxInfo.waitAckTimeout);
            if (pCmdCallback != NULL)
			{
				//各指令的对应reply的回调函数进行处理
				pCmdCallback(ret, NULL, 0);
				pCmdCallback = NULL;
			}
			CmdPacketTxInfo.status = TX_STA_IDLE;
		}

	}

}

/**
  * @brief  接收数据并解析处理
  *
  * @note   先接收数据再解析数据，如果接收到note包需要发送ack包
  */
static void Face_RecvMsgProcess(void)
{

	uint8_t *pData = NULL;
	pData = Face_GetOnePacket(); //得到一包数据并检验校验和
	
    if (pData != NULL)
	{
		err_process(0);
		Face_ParseRxPacket(pData); //解析数据
	}

	Face_ResendCmdPacket();		 //超时重发命令包
}


static void Face_TimeoutDeal(void)
{
	uint32_t currentTime = OSAL_GetTickCount();
	Face_DealParam_stu_t DealParam;

	if ((faceModuleStatus.timeout != FOREVER_TIME_OUT)											 //非永远不超时
		&& (OSAL_PastTime(currentTime, faceModuleStatus.start_time) > faceModuleStatus.timeout)) //判断是否超时
	{
		FACE_TASK_LOG("power on timeout\r\n");
		faceModuleStatus.timeout = FOREVER_TIME_OUT;
		faceModuleStatus.curStatus = FACE_STATUS_EXECUTE;
		FaceEncrypt_Set_EnFlag(1); //加密通信
		Face_Event_Update();
		err_process(1);
	}
}

/**
  * @brief 创建周期事件
  * @param 
  * @note  
  */
static void Face_Create_Repeat_Event(void)
{
	/* 创建定时处理人脸协议 */
	OSAL_EventRepeatCreate(COMP_FACE, EVENT_FACE_PROTOCOL, 10, EVT_PRIORITY_MEDIUM);
	/* 创建超时检测协议 */
	OSAL_EventRepeatCreate(COMP_FACE, EVENT_FACE_TIME_OUT, 20, EVT_PRIORITY_MEDIUM);
	/*人脸模组环形消息处理*/
	OSAL_EventRepeatCreate(COMP_FACE, EVENT_FACE_MODULE_MSG, 20, EVT_PRIORITY_MEDIUM);
}



/**
  * @brief 删除周期事件
  * @param 
  * @note  
  */
static void Face_Delete_Event(void)
{
	OSAL_EventDelete(COMP_FACE, EVENT_FACE_PROTOCOL);
	OSAL_EventDelete(COMP_FACE, EVENT_FACE_TIME_OUT);
	OSAL_EventDelete(COMP_FACE, EVENT_FACE_MODULE_MSG);
}

/**
  * @brief 创建人脸数据读取缓冲区队列
  *
  * @note 
  */
static void Face_CreateRingBuffHandle(void)
{
	static FlagStatus firstPowerOn = SET;
	if (firstPowerOn == SET)
	{
		FaceTxCmd_rbHandle = OSAL_RingBufferCreate(FACE_TX_CMD_BUFF_NUM, sizeof(SensetimeTxCmdMsg_stu_t));

		MasterOperate_rbHandle = OSAL_RingBufferCreate(FACE_TX_CMD_BUFF_NUM, sizeof(Face_Param_stu_t));
		
		if (uartFace_rbHandle == NULL)
		{
			uartFace_rbHandle = OSAL_RingBufferCreate(500, 1);
		}
		firstPowerOn = RESET;
	}
}

/**
  * @brief 清除人脸发送和设置缓存数据
  *
  * @note  
  */
static void Face_ResetSenseRingBuffData(void)
{
	OSAL_RingBufferReset(FaceTxCmd_rbHandle);
	OSAL_RingBufferReset(MasterOperate_rbHandle);
	OSAL_RingBufferReset(uartFace_rbHandle);
}

//人脸串口回调函数
static void Face_ReceiveCb(VirtualHardware_enum_t dev, void *data, uint32_t len)
{
	if (uartFace_rbHandle == NULL)
	{
		return;
	}
	for (uint32_t i = 0; i < len; i++)
	{
		uint8_t tmp = ((uint8_t *)data)[i];
		if (OSAL_RingBufferWrite(uartFace_rbHandle, &tmp) != SUCCESS)
		{
			FACE_TASK_LOG("face ringbuff write err\r\n");
			return;
		}
	}
}



/**
  * @brief  人脸初始化
  *
  * @note
  */
static void Face_ProtocolInit()
{
	__EFRAM static uint8_t init_flag = 0;
	uint8_t faceVersion[FACE_VERSION_LEN+1] = {0};
	uint8_t len = 0;
	CmdPacketTxInfo.status = TX_STA_IDLE;


	ErrorStatus ret = Face_Read_Version(faceVersion, &len);
	if (ret == ERROR || init_flag == 0)
	{
		init_flag = 1;
		FACE_TASK_LOG("get version");
		Face_Get_Version();
	}
	else
	{
		FACE_TASK_LOG("face version : %s", faceVersion);
	}
}

/**
  * @brief  Face_Task任务函数
  *
  * @note   1.任务函数内不能写阻塞代码
  *         2.任务函数每次运行只处理一个事件
  *         3.任务函数必须添加到osal_config.h文件里面
  *
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Face_Task(uint32_t event)
{
	if (event & EVENT_SYS_START) //任务启动
	{
		FACE_TASK_LOG("face task start\r\n");
		/* 打开底层设备 */
		Face_CreateRingBuffHandle();
		Device_RegisteredCB(VHW_UART_FACE, Face_ReceiveCb);
		Face_Create_Repeat_Event();		//创建事件
		FP5V_POWER_ON;
		/* 人脸初始化 */
		Face_ProtocolInit();

		/* 注册对外开放的API接口 */
		SYS_API(Face_Abort_Current_Operation);
		SYS_API(Face_Verity_Start);
		SYS_API(Face_Delete_Verity_Start);
		SYS_API(Face_Enroll_Start);
		SYS_API(Face_Delete_Start);
		SYS_API(Face_Read_Version);
		SYS_API(Face_Read_Model);
		SYS_API(Face_Set_Enc_Key);
		SYS_API(Face_Factory);
		SYS_API(Face_Set_Demo_Mode);
		SYS_API(Face_OTA_Start);
		SYS_API(Face_Get_FaceModule_CurMode);

		return (event ^ EVENT_SYS_START);
	}

	/* 休眠处理 */
	if (event & EVENT_SYS_SLEEP)
	{
		Face_ResetSenseRingBuffData();
		Face_Delete_Event();
		Device_Disable(VHW_UART_FACE);
		FACE_MODULE_POWER_OFF;
		FP5V_POWER_OFF;
		faceModuleStatus.curStatus = FACE_STATUS_POWER_DOWN;
		return (event ^ EVENT_SYS_SLEEP);
	}


	/* 发送给人脸数据的循环队列处理 */
	if (event & EVENT_FACE_MODULE_MSG)
	{
		Face_SendRingBuffDataProcess();
		return (event ^ EVENT_FACE_MODULE_MSG);
	}

	/* 人脸接收数据处理 */
	if (event & EVENT_FACE_PROTOCOL)
	{
		Face_RecvMsgProcess();
		return (event ^ EVENT_FACE_PROTOCOL);
	}

	/* 人脸任务超时事件 */
	if (event & EVENT_FACE_TIME_OUT)
	{
		Face_TimeoutDeal();
		return (event ^ EVENT_FACE_TIME_OUT);
	}

	return 0;
}
COMPONENT_TASK_EXPORT(COMP_FACE, Face_Task, FACE_NV_SIZE);
